/*
 * To change this license header, choose License Headers in Project Properties.
 * To change this template file, choose Tools | Templates
 * and open the template in the editor.
 */
package mp.weixin.WXpublic;

import mp.weixin.WXpublic.BaseReceiveMessage.ReceiveTypeEnum;
import mp.weixin.WXpublic.receive.RImageEntity;
import mp.weixin.WXpublic.receive.RLinkEntity;
import mp.weixin.WXpublic.receive.RLocationEntity;
import mp.weixin.WXpublic.receive.RShortVideoEntity;
import mp.weixin.WXpublic.receive.RTextEntity;
import mp.weixin.WXpublic.receive.RVideoEntity;
import mp.weixin.WXpublic.receive.RVoiceEntity;
import org.jdom.JDOMException;
import org.jdom.input.SAXBuilder;
import org.xml.sax.InputSource;
import java.io.IOException;
import java.io.StringReader;
import java.util.Date;
import org.jdom.Element;
import org.jdom.Document;
import mp.weixin.WXpublic.BaseEvent.EventEnum;
import mp.weixin.WXpublic.receive.event.ClickEventEntity;
import mp.weixin.WXpublic.receive.event.LocationEventEntity;
import mp.weixin.WXpublic.receive.event.ScanEventEntity;
import mp.weixin.WXpublic.receive.event.SubscribeEventEntity;
import mp.weixin.WXpublic.receive.event.TemplateSendJobFinish;
import mp.weixin.WXpublic.receive.event.UnSubscribeEventEntity;
import mp.weixin.WXpublic.receive.event.ViewEventEntity;

/**
 *
 * @author 王仲秋
 */
public class MessageConvert {

    private MessageListener ml;

    public BaseSendMessage preConvert(String message, String echostr) throws JDOMException, IOException {
//        System.out.println(message);
        StringReader xmlReader = new StringReader(message);
        /**
         * **创建新的输入源SAX 解析器将使用 InputSource 对象来确定如何读取 XML 输入
         */
        InputSource xmlSource = new InputSource(xmlReader);
        /**
         * *创建一个SAXBuilder*
         */
        SAXBuilder builder = new SAXBuilder();
        /**
         * *通过输入源SAX构造一个Document**
         */
        Document doc = builder.build(xmlSource);
        /**
         * *获得根节点**
         */
        Element elt = doc.getRootElement();
        /**
         * *获得BODY节点**
         */
        Element msgType = elt.getChild("MsgType");
        Element toUserName = elt.getChild("ToUserName");
        Element createTime = elt.getChild("CreateTime");
        Element fromUserName = elt.getChild("FromUserName");
        String msgTypeStr = msgType.getText();
        String toUserNameStr = toUserName.getText();
        String createTimeStr = createTime.getText();
        String fromUserNameStr = fromUserName.getText();
        ReceiveTypeEnum messageType = ReceiveTypeEnum.getEnumByType(msgTypeStr);
        BaseSendMessage bsm = null;
        switch (messageType) {
            case LOCATION: {
                RLocationEntity le = new RLocationEntity();
                le.setFromUserName(fromUserNameStr);
                le.setToUserName(toUserNameStr);
                Date date = new Date(Long.parseLong(createTimeStr));
                le.setCreateTime(date);
                Element locationX = elt.getChild("Location_X");
                Element locationY = elt.getChild("Location_Y");
                Element scale = elt.getChild("Scale");
                Element label = elt.getChild("Label");
                Element msgId = elt.getChild("MsgId");
                le.setLabel(label.getText());
                le.setLocationX(locationX.getText());
                le.setLocationY(locationY.getText());
                le.setScale(scale.getText());
                le.setMsgId(Long.parseLong(msgId.getText()));
                bsm = ml.location(le);
                if (bsm != null) {
                    bsm.setCreateTime(new Date());
                    bsm.setFromUserName(le.getToUserName());
                    bsm.setToUserName(le.getFromUserName());
                }
            }
            break;
            case TEXT: {
                RTextEntity te = new RTextEntity();
                te.setFromUserName(fromUserNameStr);
                te.setToUserName(toUserNameStr);
                Date date = new Date(Long.parseLong(createTimeStr));
                te.setCreateTime(date);

                Element content = elt.getChild("Content");
                Element msgId = elt.getChild("MsgId");

                te.setContent(content.getText());
                te.setMsgId(Long.parseLong(msgId.getText()));
                bsm = ml.text(te);
                if (bsm != null) {
                    bsm.setCreateTime(new Date());
                    bsm.setFromUserName(te.getToUserName());
                    bsm.setToUserName(te.getFromUserName());
                }
            }
            break;
            case IMAGE: {
                RImageEntity ie = new RImageEntity();
                ie.setFromUserName(fromUserNameStr);
                ie.setToUserName(toUserNameStr);
                Date date = new Date(Long.parseLong(createTimeStr));
                ie.setCreateTime(date);

                Element picUrl = elt.getChild("PicUrl");
                Element mediaId = elt.getChild("MediaId");
                Element msgId = elt.getChild("MsgId");

                ie.setPicUrl(picUrl.getText());
                ie.setMediaId(mediaId.getText());
                ie.setMsgId(Long.parseLong(msgId.getText()));
                bsm = ml.image(ie);
                if (bsm != null) {
                    bsm.setCreateTime(new Date());
                    bsm.setFromUserName(ie.getToUserName());
                    bsm.setToUserName(ie.getFromUserName());
                }
            }
            break;
            case VOICE: {
                RVoiceEntity ve = new RVoiceEntity();
                ve.setFromUserName(fromUserNameStr);
                ve.setToUserName(toUserNameStr);
                Date date = new Date(Long.parseLong(createTimeStr));
                ve.setCreateTime(date);

                Element format = elt.getChild("Format");
                Element mediaId = elt.getChild("MediaId");
                Element msgId = elt.getChild("MsgId");

                ve.setFormat(format.getText());
                ve.setMediaId(mediaId.getText());
                ve.setMsgId(Long.parseLong(msgId.getText()));
                bsm = ml.voice(ve);
                if (bsm != null) {
                    bsm.setCreateTime(new Date());
                    bsm.setFromUserName(ve.getToUserName());
                    bsm.setToUserName(ve.getFromUserName());
                }
            }
            break;
            case VIDEO: {
                RVideoEntity ve = new RVideoEntity();
                ve.setFromUserName(fromUserNameStr);
                ve.setToUserName(toUserNameStr);
                Date date = new Date(Long.parseLong(createTimeStr));
                ve.setCreateTime(date);

                Element thumbMediaId = elt.getChild("ThumbMediaId");
                Element mediaId = elt.getChild("MediaId");
                Element msgId = elt.getChild("MsgId");

                ve.setThumbMediaId(thumbMediaId.getText());
                ve.setMediaId(mediaId.getText());
                ve.setMsgId(Long.parseLong(msgId.getText()));
                bsm = ml.video(ve);
                if (bsm != null) {
                    bsm.setCreateTime(new Date());
                    bsm.setFromUserName(ve.getToUserName());
                    bsm.setToUserName(ve.getFromUserName());
                }
            }
            break;
            case SHORTVIDEO: {
                RShortVideoEntity rsve = new RShortVideoEntity();
                rsve.setFromUserName(fromUserNameStr);
                rsve.setToUserName(toUserNameStr);
                Date date = new Date(Long.parseLong(createTimeStr));
                rsve.setCreateTime(date);

                Element thumbMediaId = elt.getChild("ThumbMediaId");
                Element mediaId = elt.getChild("MediaId");
                Element msgId = elt.getChild("MsgId");

                rsve.setThumbMediaId(thumbMediaId.getText());
                rsve.setMediaId(mediaId.getText());
                rsve.setMsgId(Long.parseLong(msgId.getText()));
                if (bsm != null) {
                    bsm = ml.shortVideo(rsve);
                    bsm.setCreateTime(new Date());
                    bsm.setFromUserName(rsve.getToUserName());
                    bsm.setToUserName(rsve.getFromUserName());
                }
            }
            break;
            case LINK: {
                RLinkEntity rle = new RLinkEntity();
                rle.setFromUserName(fromUserNameStr);
                rle.setToUserName(toUserNameStr);
                Date date = new Date(Long.parseLong(createTimeStr));
                rle.setCreateTime(date);

                Element title = elt.getChild("Title");
                Element description = elt.getChild("Description");
                Element url = elt.getChild("Url");
                Element msgId = elt.getChild("MsgId");

                rle.setTitle(title.getText());
                rle.setDescription(description.getText());
                rle.setUrl(url.getText());
                rle.setMsgId(Long.parseLong(msgId.getText()));
                bsm = ml.link(rle);
                if (bsm != null) {
                    bsm.setCreateTime(new Date());
                    bsm.setFromUserName(rle.getToUserName());
                    bsm.setToUserName(rle.getFromUserName());
                }
            }
            break;
            case EVENT: {
                bsm = eventEntityConvert(elt);
            }
            break;
        }
        return bsm;
    }

    private BaseSendMessage eventEntityConvert(Element elt) {
        BaseEvent be = null;
        BaseSendMessage scanAndSubscribe = null;
        Element toUserName = elt.getChild("ToUserName");
        Element createTime = elt.getChild("CreateTime");
        Element fromUserName = elt.getChild("FromUserName");
        String toUserNameStr = toUserName.getText();
        String createTimeStr = createTime.getText();
        String fromUserNameStr = fromUserName.getText();
        Element event = elt.getChild("Event");
        String eventStr = event.getText();
        EventEnum ee = EventEnum.getEventByType(eventStr);
        switch (ee) {
            case SUBSCRIBE: {
                be = new SubscribeEventEntity();
                SubscribeEventEntity sub = (SubscribeEventEntity) be;
                Element ticket = elt.getChild("Ticket");
                Element eventKey = elt.getChild("EventKey");
                sub.setCreateTime(new Date(Long.parseLong(createTimeStr)));
                sub.setFromUserName(fromUserNameStr);
                sub.setToUserName(toUserNameStr);

                if (ticket != null) {
                    scanAndSubscribe = ml.scanAndSubscribe(sub);
                    ScanEventEntity see = new ScanEventEntity();
                    see.setCreateTime(new Date(Long.parseLong(createTimeStr)));
                    see.setFromUserName(fromUserNameStr);
                    see.setToUserName(toUserNameStr);
                    see.setTicket(ticket.getText());
                    see.setEventKey(eventKey.getText());
                    sub.setScan(see);
                } else {
                    scanAndSubscribe = ml.subscribe(sub);
                    ScanEventEntity see = new ScanEventEntity();
                    see.setCreateTime(new Date(Long.parseLong(createTimeStr)));
                    see.setFromUserName(fromUserNameStr);
                    see.setToUserName(toUserNameStr);
                    see.setEventKey(eventKey.getText());
                    sub.setScan(see);
                }
                if (scanAndSubscribe != null) {
                    scanAndSubscribe.setCreateTime(new Date());
                    scanAndSubscribe.setFromUserName(toUserNameStr);
                    scanAndSubscribe.setToUserName(fromUserNameStr);
                }
            }
            break;
            case UNSUBSCRIBE: {
                be = new UnSubscribeEventEntity();
                UnSubscribeEventEntity unSub = (UnSubscribeEventEntity) be;
                unSub.setCreateTime(new Date(Long.parseLong(createTimeStr)));
                scanAndSubscribe = ml.unsubscribe(unSub);
                if (scanAndSubscribe != null) {
                    scanAndSubscribe.setCreateTime(new Date());
                    scanAndSubscribe.setFromUserName(unSub.getToUserName());
                    scanAndSubscribe.setToUserName(unSub.getFromUserName());
                }
            }
            break;
            case SCAN: {
                be = new ScanEventEntity();
                ScanEventEntity scan = (ScanEventEntity) be;
                Element eventKey = elt.getChild("EventKey");
                Element ticket = elt.getChild("Ticket");
                scan.setEventKey(eventKey.getText());
                scan.setTicket(ticket.getText());
                scan.setCreateTime(new Date(Long.parseLong(createTimeStr)));
                scan.setFromUserName(fromUserNameStr);
                scan.setToUserName(toUserNameStr);
                scanAndSubscribe = ml.scan(scan);
                if (scanAndSubscribe != null) {
                    scanAndSubscribe.setCreateTime(new Date());
                    scanAndSubscribe.setFromUserName(scan.getToUserName());
                    scanAndSubscribe.setToUserName(scan.getFromUserName());
                }
            }
            break;
            case LOCATION: {
                be = new LocationEventEntity();
                LocationEventEntity location = (LocationEventEntity) be;
                Element latitude = elt.getChild("Latitude");
                Element longitude = elt.getChild("Longitude");
                Element precision = elt.getChild("Precision");
                location.setCreateTime(new Date(Long.parseLong(createTimeStr)));
                location.setFromUserName(fromUserNameStr);
                location.setToUserName(toUserNameStr);
                location.setLatitude(latitude.getText());
                location.setLongitude(longitude.getText());
                location.setPrecision(precision.getText());
                scanAndSubscribe = ml.location(location);
                if (scanAndSubscribe != null) {
                    scanAndSubscribe.setCreateTime(new Date());
                    scanAndSubscribe.setFromUserName(location.getToUserName());
                    scanAndSubscribe.setToUserName(location.getFromUserName());
                }
            }
            break;
            case VIEW: {
                be = new ViewEventEntity();
                ViewEventEntity vee = (ViewEventEntity) be;
                Element eventKey = elt.getChild("EventKey");
                vee.setCreateTime(new Date(Long.parseLong(createTimeStr)));
                vee.setFromUserName(fromUserNameStr);
                vee.setToUserName(toUserNameStr);
                vee.setEventKey(eventKey.getText());
                scanAndSubscribe = ml.view(vee);
                if (scanAndSubscribe != null) {
                    scanAndSubscribe.setCreateTime(new Date());
                    scanAndSubscribe.setFromUserName(vee.getToUserName());
                    scanAndSubscribe.setToUserName(vee.getFromUserName());
                }
            }
            break;
            case CLICK: {
                be = new ClickEventEntity();
                ClickEventEntity cee = (ClickEventEntity) be;
                Element eventKey = elt.getChild("EventKey");
                cee.setCreateTime(new Date(Long.parseLong(createTimeStr)));
                cee.setFromUserName(fromUserNameStr);
                cee.setToUserName(toUserNameStr);
                cee.setEventKey(eventKey.getText());
                scanAndSubscribe = ml.click(cee);
                if (scanAndSubscribe != null) {
                    scanAndSubscribe.setCreateTime(new Date());
                    scanAndSubscribe.setFromUserName(cee.getToUserName());
                    scanAndSubscribe.setToUserName(cee.getFromUserName());
                }
            }
            break;
            case TEMPLATESENDJOBFINISH:{
                be = new TemplateSendJobFinish();
                TemplateSendJobFinish tsjf = (TemplateSendJobFinish) be;
                Element msgId = elt.getChild("MsgID");
                Element status = elt.getChild("Status");
                tsjf.setCreateTime(new Date(Long.parseLong(createTimeStr)));
                tsjf.setFromUserName(fromUserNameStr);
                tsjf.setToUserName(toUserNameStr);
                tsjf.setMsgId(Long.parseLong(msgId.getText()));
                tsjf.setStatus(status.getText());
                scanAndSubscribe = ml.templateSendJobFinish(tsjf);
                if(scanAndSubscribe != null){
                    scanAndSubscribe.setCreateTime(new Date());
                    scanAndSubscribe.setFromUserName(tsjf.getToUserName());
                    scanAndSubscribe.setToUserName(tsjf.getFromUserName());
                }
            }
        }
        return scanAndSubscribe;
    }

    /**
     * 现在之支持单事件的绑定 只能绑定一个事件监听器 使用的是最后的那个监听器
     *
     * @param ml
     */
    public void bindingListener(MessageListener ml) {
        this.ml = ml;
    }

}
